HDU 4650 Minimum Average Weight Path(floyd)

题意:

$N\le 100,M\le 10^4,N个点,M条边的图,无重边,可能有自环$
$所有节点对(u, v)的min\{\frac{dis(u, v)}{len(u, v)}\},不连通输出NO$

分析:

$floyd求一发连通性,判断NO$
$然后f[k][i][j]:=i到j长度为k的最短路$
$floyd的循环顺序是可以换的嘛,把i拿到最外面去枚举,这样可以复用数组$
$就变成f[k][j]:=i出发,长度为k到j的最短路$
$然后更新答案,注意由于有环,那么判断可不可以经过环$
$经过的话,环的答案如果比较小,显然可以无限绕环来逼近环长(极限思想嘛)$
$时间复杂度O(n^4)$

代码:

//
//  Created by TaoSama on 2016-03-12
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e2 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, m;
int f[N][N], g[N][N], con[N][N];
double ans[N][N];

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d", &n, &m) == 2) {
        memset(g, 0x3f, sizeof g);
        memset(con, 0, sizeof con);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                ans[i][j] = 1e18;
        for(int i = 1; i <= m; ++i) {
            int x, y, c; scanf("%d%d%d", &x, &y, &c);
            g[x][y] = c;
            con[x][y] = 1;
        }
        for(int k = 1; k <= n; ++k)
            for(int i = 1; i <= n; ++i)
                for(int j = 1; j <= n; ++j)
                    con[i][j] |= con[i][k] & con[k][j];
        for(int i = 1; i <= n; ++i) {
            memset(f, 0x3f, sizeof f);
            f[0][i] = 0;
            for(int l = 1; l <= n; ++l)
                for(int k = 1; k <= n; ++k)
                    for(int j = 1; j <= n; ++j)
                        f[l][j] = min(f[l][j], f[l - 1][k] + g[k][j]);
            for(int l = 1; l <= n; ++l)
                for(int j = 1; j <= n; ++j)
                    ans[i][j] = min(ans[i][j], f[l][j] * 1. / l);
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                if(!con[i][j]) printf("NO%c", " \n"[j == n]);
                else {
                    for(int k = 1; k <= n; ++k)
                        if(con[i][k] & con[k][j])
                            ans[i][j] = min(ans[i][j], ans[k][k]);
                    printf("%.3f%c", ans[i][j], " \n"[j == n]);
                }
            }
        }
    }
    return 0;
}